from flask import Flask, render_template, request, jsonify, redirect, url_for, session
import os
import sys
import shutil
from datetime import datetime
from werkzeug.utils import secure_filename

# 添加modules目录到路径
sys.path.append(os.path.join(os.path.dirname(__file__), 'modules'))

from modules.database import db_manager
from modules.audio_player import audio_player
from modules.scheduler import scheduler
from modules.auth import auth_manager, login_required
from config import AUDIO_DIR, DEFAULT_VOLUME


def _estimate_audio_duration(file_size):
    """估算音频时长（简化处理）
    
    Args:
        file_size (int): 文件大小（字节）
        
    Returns:
        int: 估算的时长（秒）
    """
    # 简化的估算方法，实际应用中应使用音频处理库
    # 假设平均比特率为128kbps
    bitrate = 128 * 1024  # 128 kbps = 128 * 1024 bps
    duration_seconds = (file_size * 8) // bitrate
    return max(1, duration_seconds)  # 至少1秒


def create_app():
    app = Flask(__name__)
    app.config['SECRET_KEY'] = 'bell-system-secret-key-2025'  # 在实际应用中应该使用更安全的密钥
    
    # 登录页面路由
    @app.route('/login')
    def login():
        # 如果用户已登录，重定向到主页
        if 'username' in session:
            return redirect(url_for('index'))
        return render_template('login.html')
    
    # 登录处理路由
    @app.route('/login', methods=['POST'])
    def login_post():
        data = request.get_json()
        username = data.get('username')
        password = data.get('password')
        
        # 验证用户凭据
        if auth_manager.verify_user(username, password):
            # 登录成功，设置会话
            session['username'] = username
            return jsonify({'success': True})
        else:
            return jsonify({'success': False}), 401
    
    # 登出路由
    @app.route('/logout')
    def logout():
        # 清除会话
        session.pop('username', None)
        return redirect(url_for('login'))
    
    # 主页路由（需要登录）
    @app.route('/')
    @login_required
    def index():
        return render_template('index.html')
    
    # 方案管理页面路由
    @app.route('/schedule')
    @login_required
    def schedule():
        return render_template('schedule.html')
    
    # 铃声库管理页面路由
    @app.route('/audio')
    @login_required
    def audio():
        return render_template('audio.html')
    
    # 系统设置页面路由
    @app.route('/settings')
    @login_required
    def settings():
        return render_template('settings.html')
    
    # 获取所有方案
    @app.route('/api/plans')
    @login_required
    def get_plans():
        plans = db_manager.get_all_plans()
        return jsonify(plans)
    
    # 获取启用的方案
    @app.route('/api/active_plans')
    @login_required
    def get_active_plans():
        plans = db_manager.get_active_plans()
        return jsonify(plans)
    
    # 获取方案详情
    @app.route('/api/plans/<int:plan_id>')
    @login_required
    def get_plan(plan_id):
        plan = db_manager.get_plan_by_id(plan_id)
        if plan:
            bell_times = db_manager.get_bell_times_by_plan(plan_id)
            return jsonify({'plan': plan, 'bell_times': bell_times})
        return jsonify({'error': 'Plan not found'}), 404
    
    # 创建新方案
    @app.route('/api/plans', methods=['POST'])
    @login_required
    def create_plan():
        data = request.get_json()
        name = data.get('name')
        type = data.get('type', 'default')
        is_active = data.get('is_active', True)
        
        plan_id = db_manager.add_plan(name, type, is_active)
        if plan_id > 0:
            return jsonify({'id': plan_id, 'message': 'Plan created successfully'}), 201
        return jsonify({'error': 'Failed to create plan'}), 500
    
    # 更新方案
    @app.route('/api/plans/<int:plan_id>', methods=['PUT'])
    @login_required
    def update_plan(plan_id):
        data = request.get_json()
        name = data.get('name')
        type = data.get('type')
        is_active = data.get('is_active')
        
        result = db_manager.update_plan(plan_id, name, type, is_active)
        if result:
            return jsonify({'message': 'Plan updated successfully'})
        return jsonify({'error': 'Failed to update plan'}), 500
    
    # 删除方案
    @app.route('/api/plans/<int:plan_id>', methods=['DELETE'])
    @login_required
    def delete_plan(plan_id):
        result = db_manager.delete_plan(plan_id)
        if result:
            return jsonify({'message': 'Plan deleted successfully'})
        return jsonify({'error': 'Failed to delete plan'}), 500
    
    # 添加铃声时间点
    @app.route('/api/bell_times', methods=['POST'])
    @login_required
    def add_bell_time():
        data = request.get_json()
        plan_id = data.get('plan_id')
        time = data.get('time')
        audio_file = data.get('audio_file')
        # 使用固定的铃声类型和音量
        bell_type = 'default'
        volume = 80
        
        bell_time_id = db_manager.add_bell_time(plan_id, time, bell_type, audio_file, volume)
        if bell_time_id > 0:
            return jsonify({'id': bell_time_id, 'message': 'Bell time added successfully'}), 201
        return jsonify({'error': 'Failed to add bell time'}), 500
    
    # 删除方案的所有铃声时间点
    @app.route('/api/plans/<int:plan_id>/bell_times', methods=['DELETE'])
    @login_required
    def delete_bell_times_by_plan(plan_id):
        result = db_manager.delete_bell_times_by_plan(plan_id)
        if result:
            return jsonify({'message': 'Bell times deleted successfully'})
        return jsonify({'error': 'Failed to delete bell times'}), 500
    
    # 获取所有音频文件
    @app.route('/api/audio_files')
    @login_required
    def get_audio_files():
        audio_files = db_manager.get_all_audio_files()
        return jsonify(audio_files)
    
    # 获取单个音频文件
    @app.route('/api/audio_files/<int:audio_id>')
    @login_required
    def get_audio_file(audio_id):
        # 这里可以实现获取单个音频文件的逻辑
        return jsonify({'message': 'Not implemented'}), 501
    
    # 上传音频文件
    @app.route('/api/upload_audio', methods=['POST'])
    @login_required
    def upload_audio():
        if 'audio_file' not in request.files:
            return jsonify({'error': 'No file provided'}), 400
        
        file = request.files['audio_file']
        if file.filename == '':
            return jsonify({'error': 'No file selected'}), 400
        
        if file and file.filename:
            # 验证文件扩展名
            filename = secure_filename(file.filename)
            file_ext = os.path.splitext(filename)[1].lower()
            if file_ext not in ['.mp3', '.wav', '.ogg']:
                return jsonify({'error': 'Unsupported file format'}), 400
            
            # 确保音频目录存在
            if not os.path.exists(AUDIO_DIR):
                os.makedirs(AUDIO_DIR)
            
            # 保存文件到音频目录
            file_path = os.path.join(AUDIO_DIR, filename)
            
            # 如果文件已存在，添加序号
            counter = 1
            original_filename, ext = os.path.splitext(filename)
            while os.path.exists(file_path):
                new_filename = f"{original_filename}_{counter}{ext}"
                file_path = os.path.join(AUDIO_DIR, new_filename)
                counter += 1
            
            try:
                file.save(file_path)
            except Exception as e:
                return jsonify({'error': f'Failed to save file: {str(e)}'}), 500
            
            # 估算音频时长（简化处理）
            try:
                file_size = os.path.getsize(file_path)
                duration = _estimate_audio_duration(file_size)
            except Exception as e:
                print(f"获取文件大小时出错: {e}")
                duration = 0
            
            # 保存到数据库
            audio_id = db_manager.add_audio_file(
                os.path.basename(file_path),
                file_path,
                duration
            )
            
            if audio_id > 0:
                return jsonify({
                    'id': audio_id,
                    'filename': os.path.basename(file_path),
                    'path': file_path,
                    'duration': duration,
                    'message': 'File uploaded successfully'
                }), 201
            else:
                # 如果数据库保存失败，删除已保存的文件
                if os.path.exists(file_path):
                    try:
                        os.remove(file_path)
                    except Exception as e:
                        print(f"删除文件时出错: {e}")
                return jsonify({'error': 'Failed to save file info to database'}), 500
        return jsonify({'error': 'No file provided'}), 400
    
    # 删除音频文件
    @app.route('/api/audio_files/<int:audio_id>', methods=['DELETE'])
    @login_required
    def delete_audio_file(audio_id):
        # 从数据库中获取音频文件信息
        audio_file = None
        try:
            # 获取所有音频文件
            audio_files = db_manager.get_all_audio_files()
            for af in audio_files:
                if af['id'] == audio_id:
                    audio_file = af
                    break
        except Exception as e:
            return jsonify({'error': f'Failed to fetch audio file: {str(e)}'}), 500
        
        if not audio_file:
            return jsonify({'error': 'Audio file not found'}), 404
        
        # 从数据库中删除记录
        success = db_manager.delete_audio_file(audio_id)
        
        if success:
            # 删除文件系统中的文件
            file_path = audio_file['path']
            if os.path.exists(file_path):
                try:
                    os.remove(file_path)
                except Exception as e:
                    print(f"删除文件时出错: {e}")
            
            return jsonify({'message': 'Audio file deleted successfully'})
        else:
            return jsonify({'error': 'Failed to delete audio file from database'}), 500
    
    # 获取星期方案设置
    @app.route('/api/weekday_plans')
    @login_required
    def get_weekday_plans():
        weekday_plans = db_manager.get_all_weekday_plans()
        return jsonify(weekday_plans)
    
    # 保存星期方案设置
    @app.route('/api/weekday_plans', methods=['POST'])
    @login_required
    def save_weekday_plans():
        data = request.get_json()
        for weekday, plan_id in data.items():
            # 处理null值
            if plan_id is None or plan_id == "":
                db_manager.save_weekday_plan(weekday, None)
            else:
                db_manager.save_weekday_plan(weekday, int(plan_id))
        return jsonify({'message': 'Weekday plans saved successfully'})
    
    # 播放音频文件
    @app.route('/api/play_audio', methods=['POST'])
    @login_required
    def play_audio():
        data = request.get_json()
        file_path = data.get('file_path')
        volume = data.get('volume', 80)
        
        if not file_path:
            return jsonify({'error': 'File path is required'}), 400
        
        # 检查文件是否存在
        if not os.path.exists(file_path):
            return jsonify({'error': 'Audio file not found'}), 404
        
        # 播放音频
        result = audio_player.play_audio(file_path, volume)
        if result:
            return jsonify({'message': 'Audio playing started'})
        else:
            return jsonify({'error': 'Failed to play audio'}), 500
    
    # 停止音频播放
    @app.route('/api/stop_audio', methods=['POST'])
    @login_required
    def stop_audio():
        audio_player.stop_audio()
        return jsonify({'message': 'Audio stopped'})
    
    # 启动调度器
    @app.route('/api/start_scheduler', methods=['POST'])
    @login_required
    def start_scheduler():
        scheduler.start_scheduler()
        return jsonify({'message': 'Scheduler started'})
    
    # 停止调度器
    @app.route('/api/stop_scheduler', methods=['POST'])
    @login_required
    def stop_scheduler():
        scheduler.stop_scheduler()
        return jsonify({'message': 'Scheduler stopped'})
    
    # 跳过下次铃声
    @app.route('/api/skip_next_bell', methods=['POST'])
    @login_required
    def skip_next_bell():
        skipped_bell = scheduler.skip_next_bell()
        if skipped_bell:
            return jsonify({'message': 'Next bell skipped', 'skipped_bell': skipped_bell})
        else:
            return jsonify({'message': 'No bell to skip'}), 404
    
    # 获取下一个铃声时间
    @app.route('/api/next_bell')
    @login_required
    def get_next_bell():
        # 重新加载调度器以确保获取最新的铃声时间
        scheduler.load_schedule()
        next_bell = scheduler.get_next_bell_time()
        if next_bell:
            return jsonify(next_bell)
        else:
            return jsonify({'message': 'No upcoming bells'}), 404
    
    # 获取系统设置
    @app.route('/api/settings')
    @login_required
    def get_settings():
        # 返回当前系统设置
        return jsonify({
            'default_volume': DEFAULT_VOLUME,
            'audio_dir': AUDIO_DIR,
            'database_path': os.path.join(os.path.dirname(__file__), 'bell_system.db')
        })
    
    # 保存系统设置
    @app.route('/api/settings', methods=['POST'])
    @login_required
    def save_settings():
        data = request.get_json()
        default_volume = data.get('default_volume', DEFAULT_VOLUME)
        
        # 在实际应用中，这里应该保存设置到配置文件或数据库
        # 目前我们只是模拟保存操作
        print(f"保存设置: 默认音量 = {default_volume}%")
        
        # 更新音频播放器的音量
        audio_player.set_volume(default_volume)
        
        return jsonify({'message': 'Settings saved successfully'})
    
    # 修改密码API
    @app.route('/api/change_password', methods=['POST'])
    @login_required
    def change_password():
        data = request.get_json()
        current_password = data.get('current_password')
        new_password = data.get('new_password')
        confirm_password = data.get('confirm_password')
        
        username = session.get('username')
        
        # 验证输入
        if not current_password or not new_password or not confirm_password:
            return jsonify({'success': False, 'message': '所有字段都是必填的'}), 400
        
        if new_password != confirm_password:
            return jsonify({'success': False, 'message': '新密码和确认密码不匹配'}), 400
        
        if len(new_password) < 6:
            return jsonify({'success': False, 'message': '密码长度至少为6位'}), 400
        
        # 调用认证管理器修改密码
        if auth_manager.change_password(username, current_password, new_password):
            return jsonify({'success': True, 'message': '密码修改成功'})
        else:
            return jsonify({'success': False, 'message': '当前密码错误'}), 400
    
    return app

if __name__ == '__main__':
    app = create_app()
    app.run(debug=True, host='0.0.0.0', port=5000)